﻿using System;
using LinearAlgebra.Matrices;
using LinearAlgebra.Vectors.Numeric;
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using Real = System.Double;

namespace LinearAlgebraTests
{
	/// <summary>
	/// Summary description for UnitTest1
	/// </summary>
	[TestClass]
	public class PrimaryTests
	{
		private TestContext testContextInstance;

		/// <summary>
		///Gets or sets the test context which provides
		///information about and functionality for the current test run.
		///</summary>
		public TestContext TestContext
		{
			get { return testContextInstance; }
			set { testContextInstance = value; }
		}			

		[TestMethod]		
		public void VectorOperations()
		{
			for( int n = 1; n < 100; n++ )
			{
				RealVector u = RealVector.Random( n, n, 0, 1000 );
				RealVector v = RealVector.CreateFrom( u ); //make a copy				
				
				//in place operations
				u.Shuffle( 36 ).Sort();
				v.Shuffle( 36 ).Sort();

				if( !u.Equals( v, Double.Epsilon * 2 ) ) {
					Console.WriteLine( "Vectors were not equal" );
					throw new AssertFailedException( "Vectors were not equal" );					
				}
				Console.WriteLine( "Vectors were equal" );
				//done with identity testing


			}			
		}


		[TestMethod]
		public void SquareMatrixOperations()
		{
			Random r = new Random( 36 );
			for (int i = 2; i < 500; i = i * i ) 
			{
				Matrix A = Matrix.Random( i, i, r.Next(0, 100), int.MinValue, int.MaxValue );				
				Double eps = Double.Epsilon;

				//Transpose Multiplicative Symmetry
				while( ! (A*A.GetTranspose()).IsSymmetric(eps) )
				{
					eps *= 2;
				}
				O( A.M, A.N, "Symmetric at epsilon: " + eps   );
			}
		}

		public int R( Random r )
		{
			return r.Next( 1, 1000 );
		}

		public void O( int i, int j, string text  ) {
			Console.WriteLine( String.Format( "{0}x{1}:" + text, i, j ) );
		}

		[TestMethod]
		public void Inversion()
		{		
			Console.WriteLine( "Inversions!" );
			for (int i = 10; i < 1000; i += 200 )
			{	
				Console.Write( "Case " + i + ": " );
				
				Matrix inverse = Matrix.Random( i, i, 36, 0, i*i ).
					Augment( Matrix.Identity( i, i ) )		.
					Eliminate( Double.Epsilon )	.
					Normalize()								.
					SolveByBackSubstitution()				.
					DeAugment( i );

				Matrix inverse2 = Matrix.Random( i, i, 36, 0, i*i ).GetInverse();
				if( inverse.Equals( inverse2, .000001 ) )				
					Console.WriteLine( "They are equal!" );
				else
				{
					Console.WriteLine( "Not equal!" );
					throw new Exception( "Matrices were not equal!" );
				}
				
				Matrix A = Matrix.Random( i, i, 36, 0, i*i );
				if( (A*inverse).Equals( Matrix.Identity( A.RowCount, A.RowCount ), float.Epsilon ) )
					Console.WriteLine( "A*Inverse produces Identity matrix" );
				Matrix B = (A);
				//Console.WriteLine( B.ToString() );
			}
		}

		[TestMethod]
		public void FactoryTests()
		{
			Matrix A = new Matrix(0);
			A.Add( new RealVector( 1, 2, 3, 4, 5 ) );
			A.Add( new RealVector( 5, 4, 3, 2, 1 ) );
			A.Add( 3, 9, 7, 4, 3 );			
			Console.WriteLine( A.ToString() );

			Random r = new Random( 36 );	
			for (int i = 0; i < 100; i++)
			{
				for (int j = 0; j < 100; j++)
				{					
					Matrix.Create( i, j, (x,y)=> r.NextDouble()*100 );

					Double sum = 0.0;
					Matrix.Zero( i, j ).Do( (x)=>sum+=x );
					if( sum != 0.0 )
						throw new Exception( "Zero Matrix had non zero values in it!" );
					else
					{
						Console.WriteLine( "Zero matrix is all zeroes!" );
					}
				}
			}
		}

		public void Mangles()
		{
			
		}
	}
}
